package com.fxm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fxm.constant.RedisConstants;
import com.fxm.domain.Rule;
import com.fxm.domain.User;
import com.fxm.returns.RespCode;
import com.fxm.returns.RespEntity;
import com.fxm.service.*;
import com.fxm.service.client.WeChartClientService;
import com.fxm.utils.RedisUtil;
import com.fxm.utils.TimeUtilCustomize;
import com.fxm.vo.param.OpenParam;
import com.fxm.vo.param.UserParam;
import com.fxm.vo.result.SessionResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Date;
import java.util.Objects;

/**
 * <p>
 * 微信接口 服务实现类
 * </p>
 *
 * @author fxm
 * @since 2020-12-29
 */
@Service
@Slf4j
public class WeChartServiceImpl implements WeChartService {

    @Autowired
    private WeChartClientService weChartClientService;

    @Autowired
    private UserService userService;

    @Autowired
    private SignInService signInService;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private RuleService ruleService;

    @Autowired
    private VisitService visitService;

    @Override
    public RespEntity<SessionResult> getSession(UserParam userParam) {
        log.info("获取用户参数，userParam={}", userParam);
        if (Objects.isNull(userParam)) {
            log.info("参数为空");
            return new RespEntity(RespCode.PARAMETERS_ERROR);
        }
        SessionResult sessionResult = weChartClientService.getSessionKeyAndOpenId(userParam.getCode());
        if (Objects.isNull(sessionResult)) {
            return new RespEntity(RespCode.SERVER_ERROR);
        }

        //日访问量 异步数据接入
        visitService.visitDataAccess(1);

        //URI解码
        userParam = encodeParam(userParam);
        log.info("URI解码后，Object={}", userParam);

        //根据openid判断当前用户是否存在
        User user = selectUserExist(sessionResult.getOpenid());

        if (Objects.isNull(user)) {
            //新增用户
            insertUser(userParam, sessionResult.getOpenid());
            sessionResult.setIntegral("0");
        }else {
            //检查用户是否被封禁
            if (user.getDeleted().equals(1)) {
                return new RespEntity(RespCode.IS_BAN);
            }
            //修改用户信息
            updateUser(userParam, user);
            sessionResult.setIntegral(user.getIntegral()+"");
        }

        //签到处理
        signIn(sessionResult.getOpenid());

        return new RespEntity(RespCode.SUCCESS, sessionResult);
    }


    /**
     * 签到处理
     * @param openid
     */
    private void signIn(String openid) {
        //判断今天是否是第一次登陆
        String flag = redisUtil.get(RedisConstants.key.getIsSign(openid));
        flag = StringUtils.isBlank(flag) ? "0" : flag;
        //今日第一次登陆
        if ("0".equals(flag)) {
            //去签到
            signInService.signIn(new OpenParam(openid));
            //重置答题挑战次数
            resetChallengeNum(openid);
        }
    }

    /**
     * 判断用户是否存在
     * @param openid
     * @return
     */
    private User selectUserExist(String openid) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(User::getOpenid, openid);
        User user = userService.getOne(queryWrapper);
        if (Objects.nonNull(user)) {
            return user;
        }
        return null;
    }

    /**
     * 修改用户信息
     * @param userParam
     * @param u
     */
    private void updateUser(UserParam userParam, User u) {
        User user = User.builder()
                .id(u.getId())
                .integral(u.getIntegral())
                .openid(u.getOpenid())
                .country(userParam.getCountry())
                .province(userParam.getProvince())
                .city(userParam.getCity() + "市")
                .sex(userParam.getGender())
                .picPath(userParam.getAvatarUrl())
                .username(userParam.getNickname())
                .modifiedDate(TimeUtilCustomize.parseDateToStr(TimeUtilCustomize.DATE_TIME_FORMAT, new Date()))
                .build();
        userService.updateById(user);
        log.info("修改用户信息成功，user={}", user);
    }

    /**
     * 新增用户
     * @param userParam
     */
    private void insertUser(UserParam userParam, String openid) {
        //初始化用户表
        User user = User.builder()
                .integral(0)
                .openid(openid)
                .country(userParam.getCountry())
                .province(userParam.getProvince())
                .city(userParam.getCity() + "市")
                .sex(userParam.getGender())
                .picPath(userParam.getAvatarUrl())
                .username(userParam.getNickname())
                .build();
        userService.save(user);
        log.info("新用户登陆，user={}", user);
        //初始化答题规则表
        Rule rule = Rule.builder()
                .openid(openid)
                .rule(20)
                .challenge(3)
                .build();
        ruleService.save(rule);
    }

    /**
     * URI解码
     * @param userParam
     * @return
     */
    private UserParam encodeParam(UserParam userParam) {
        if (Objects.nonNull(userParam.getCountry())) {
            String country = null;
            try {
                country = URLDecoder.decode(userParam.getCountry(), "UTF-8");
                country = URLDecoder.decode(country, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                log.error("country解码失败");
            }
            userParam.setCountry(country);
        }
        if (Objects.nonNull(userParam.getCity())) {
            String city = null;
            try {
                city = URLDecoder.decode(userParam.getCity(), "UTF-8");
                city = URLDecoder.decode(city, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                log.error("city解码失败");
            }
            userParam.setCity(city);
        }
        if (Objects.nonNull(userParam.getProvince())) {
            String province = null;
            try {
                province = URLDecoder.decode(userParam.getProvince(), "UTF-8");
                province = URLDecoder.decode(province, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                log.error("province解码失败");
            }
            userParam.setProvince(province);
        }
        if (Objects.nonNull(userParam.getNickname())) {
            String nickName = null;
            try {
                nickName = URLDecoder.decode(userParam.getNickname(), "UTF-8");
                nickName = URLDecoder.decode(nickName, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                log.error("nickName解码失败");
            }
            userParam.setNickname(nickName);
        }
        return userParam;
    }

    /**
     * 重置该用户今日答题挑战次数
     * @param openid
     */
    private void resetChallengeNum(String openid) {
        QueryWrapper<Rule> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Rule::getOpenid, openid);
        Rule one = ruleService.getOne(queryWrapper);
        Rule rule = Rule.builder()
                .id(one.getId())
                .openid(openid)
                .rule(one.getRule())
                .challenge(3)
                .build();
        ruleService.updateById(rule);
    }
}
